package rpc

import (
	"github.com/golang/protobuf/proto"
	. "leaf/core/error"
	"leaf/core/log"
	. "leaf/core/msg"
	"leaf/core/network"
	"reflect"
)

type RpcServer struct {
	*network.TcpServer
}

type RpcServerClient struct {
	network.Conn
	rpcCalls map[uint32]*RpcCall
}

func NewRpcServerClient(conn network.Conn) *RpcServerClient {
	return &RpcServerClient{
		Conn:     conn,
		rpcCalls: make(map[uint32]*RpcCall),
	}
}

func (r *RpcServerClient) SendPotoMsg(data proto.Message) {
	msg := NewMessage(0, data)
	if msg == nil {
		log.Error("msgid of %v not find", reflect.TypeOf(data).Name())
		return
	}

	r.SendMsg(msg)
}

func (r *RpcServerClient) SendMsg(msg *Message) {
	bytes, err := Marshal(msg)
	if err != nil {
		log.Debug("notify err: %v", err)
		return
	}

	err = r.WriteMsg(bytes)
	if err != nil {
		log.Error("write message error: %v", err)
	}
}

func (r *RpcServerClient) Process(head *MessageHead, msgBytes []byte) {
	if head.Type != MessageType_Rpc {
		log.Error("rpcServer process err:msg type err,head:%v", head)
		return
	}
	var replyFlag = head.Index != 0
	var reply = &Message{MessageHead: *head}
	var request = NewMessageFromBytes(head, msgBytes)
	if request == nil {
		if replyFlag {
			reply.Code = Error_Rpc_NotFind.Code()
			r.SendMsg(reply)
		}
		return
	}

	service, rpcHandler := processer.GetHandler(request.RpcMethod)
	if rpcHandler == nil {
		if replyFlag {
			reply.Code = Error_Rpc_NotFind.Code()
			r.SendMsg(reply)
		}
		return
	}
	replyMsg := rpcHandler.GetReplyMsg()
	if replyMsg != nil {
		reply.Msg = replyMsg.(proto.Message)
	}

	var msg = new(PMsg)
	msg.Request = request
	msg.Reply = reply
	if service != nil {
		service.(IServicRpcFilter).GetServicRpc().Exec(rpcHandler, msg, true)
		if replyFlag {
			r.SendMsg(reply)
		}
	} else {
		err := rpcHandler.Func(nil, msg)
		if replyFlag {
			if err != nil {
				reply.Code = err.Code()
			}
			r.SendMsg(msg.Reply)
		}
	}
}

func (r *RpcServerClient) OnClose() {

}
